package com.aiwiown.snackmq.api;

// --- 关键修复：导入 DTO，而不是服务端的内部模型 ---

import com.aiwiown.snackmq.api.exception.SnackMQClientException;
import com.aiwiown.snackmq.common.auth.AuthenticatedUser;
import com.aiwiown.snackmq.common.auth.Permission;
import com.aiwiown.snackmq.common.dto.TopicInfo;
import com.aiwiown.snackmq.common.message.Message;
import com.aiwiown.snackmq.common.routing.ExchangeType;

import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 生产者接口，定义了所有生产者客户端的核心功能。
 * 这是一个可关闭的资源，建议使用 try-with-resources 语句进行管理。
 */
public interface Producer extends AutoCloseable {

    /**
     * 启动生产者。
     *
     * @throws SnackMQClientException 如果启动失败
     */
    void start() throws SnackMQClientException;

    /**
     * 【新增】检查生产者底层的网络连接是否处于活动状态。
     *
     * @return 如果连接活跃则返回 true，否则返回 false。
     */
    boolean isActive();

    /**
     * 同步发送一条消息。
     *
     * @param message 待发送的消息
     * @return 发送结果
     * @throws SnackMQClientException 如果发送失败或超时
     */
    SendResult send(Message message) throws SnackMQClientException;

    /**
     * 异步发送一条消息，并返回一个可精确跟踪的 Future。
     * 这是推荐使用的异步发送方式。
     *
     * @param message 待发送的消息
     * @return 一个 CompletableFuture，它将在消息被 Broker 确认后完成
     */
    CompletableFuture<SendResult> sendAsync(Message message);

    /**
     * 【新增】同步发送一个消息批次。
     * 这是一种高效的方式，可以减少网络往返次数并提高吞吐量。
     * Broker 会将整个批次作为原子单元进行处理。
     *
     * @param messages 待发送的消息列表
     * @return 整个批次的发送结果
     * @throws SnackMQClientException 如果发送失败或超时
     */
    SendResult sendBatch(List<Message> messages) throws SnackMQClientException;

    /**
     * 【新增】异步发送一个消息批次。
     * 这是推荐的批量发送方式。
     *
     * @param messages 待发送的消息列表
     * @return 一个 CompletableFuture，它将在整个批次被 Broker 确认后完成
     */
    CompletableFuture<SendResult> sendBatchAsync(List<Message> messages);

    /**
     * (已废弃) 使用回调方式异步发送一条消息。
     *
     * @param message  待发送的消息
     * @param callback 发送完成后的回调
     * @deprecated 请使用返回 CompletableFuture 的 sendAsync(Message) 方法，它提供了更强大和灵活的异步处理能力。
     */
    @Deprecated
    void sendAsync(Message message, SendCallback callback);

    /**
     * 创建一个主题。
     *
     * @param topicName  主题名称
     * @param partitions 分区数量
     * @throws SnackMQClientException 如果操作失败
     */
    void createTopic(String topicName, int partitions) throws SnackMQClientException;

    /**
     * 【新增】创建一个具有指定副本数的主题。
     * 这是实现高可用的关键。
     *
     * @param topicName         主题名称
     * @param partitions        分区数量
     * @param replicationFactor 每个分区的副本数量
     */
    void createTopic(String topicName, int partitions, int replicationFactor) throws SnackMQClientException;

    /**
     * 删除一个主题。
     *
     * @param topicName 主题名称
     * @throws SnackMQClientException 如果操作失败
     */
    void deleteTopic(String topicName) throws SnackMQClientException;

    /**
     * 声明一个交换机。
     *
     * @param exchangeName 交换机名称
     * @param type         交换机类型
     * @throws SnackMQClientException 如果操作失败
     */
    void declareExchange(String exchangeName, ExchangeType type) throws SnackMQClientException;

    /**
     * 删除一个交换机。
     *
     * @param exchangeName 交换机名称
     * @throws SnackMQClientException 如果操作失败
     */
    void deleteExchange(String exchangeName) throws SnackMQClientException;

    /**
     * 绑定一个队列（主题）到交换机。
     *
     * @param queueName    队列/主题名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     * @throws SnackMQClientException 如果操作失败
     */
    void bindQueue(String queueName, String exchangeName, String routingKey) throws SnackMQClientException;

    /**
     * 【新增】解除一个队列（主题）与交换机的绑定。
     *
     * @param queueName    队列/主题名称
     * @param exchangeName 交换机名称
     * @param routingKey   绑定的路由键
     */
    void unbindQueue(String queueName, String exchangeName, String routingKey) throws SnackMQClientException;

    /**
     * 获取主题的元数据。
     *
     * @param topicName 主题名称
     * @return 包含主题信息的 TopicInfo 对象，如果不存在则返回 null
     * @throws SnackMQClientException 如果请求失败
     */
    TopicInfo getTopicMetadata(String topicName) throws SnackMQClientException;

    /**
     * 【新增】创建一个新用户。
     *
     * @param username 用户名
     * @param password 密码
     * @param roles    用户所属的角色列表
     * @throws SnackMQClientException 如果操作失败
     */
    void createUser(String username, String password, List<String> roles) throws SnackMQClientException;

    /**
     * 【新增】为一个角色设置权限。如果角色不存在，则会创建。
     *
     * @param roleName    角色名称
     * @param permissions 该角色的权限列表
     * @throws SnackMQClientException 如果操作失败
     */
    void setRolePermissions(String roleName, List<Permission> permissions) throws SnackMQClientException;

    /**
     * 【新增】删除一个用户。
     */
    void deleteUser(String username) throws SnackMQClientException;

    /**
     * 【新增】删除一个角色。
     */
    void deleteRole(String roleName) throws SnackMQClientException;

    /**
     * 【新增】使用用户名和密码向 Broker 进行认证。
     * 成功后返回一个包含用户信息的对象，通常包含一个 JWT 用于后续请求。
     *
     * @param username 用户名
     * @param password 密码
     * @return 认证成功后的用户信息对象
     * @throws SnackMQClientException 如果认证失败
     */
    AuthenticatedUser authenticate(String username, String password) throws SnackMQClientException;

}